#include "heapopt.h"
#include <logbase.h>
//heap完全树
int heapRootFree(struct heapRootInform *heaproot)
{
    if (!heaproot)
    {
        logerrorc("");
        return 0;
    }
    if (heaproot->nodes)
    {
        free(heaproot->nodes);
        heaproot->nodes = NULL;
    }
    heaproot->nodesize = heaproot->totalsize = 0;
    return 0;
}

//isBifTree，0：little,1:big
int heapRootInit(struct heapRootInform *heaproot, uint32_t totalLength, int isBigTree)
{
    if (!heaproot)
    {
        logerrorc("");
        return -1;
    }
    heapRootFree(heaproot);
    heaproot->nodes = malloc(sizeof(union heapNodeInform) * totalLength);
    if(!heaproot->nodes)
    {
        logerrorc("");
        return -1;
    }
    heaproot->totalsize = totalLength;
    heaproot->bigTreeFlag = isBigTree;
    heaproot->nodesize = 0;
    return 0;
}

int heapRootAddNode(struct heapRootInform *heaproot, const union heapNodeInform *data)
{
    if (!heaproot || !data)
    {
        logerrorc("");
        return -1;
    }
    if(heaproot->nodesize >= heaproot->totalsize)
    {
        logerrorc("heap over.%u:%u", heaproot->nodesize, heaproot->totalsize);
        return -1;
    }
    uint32_t tmpi = heaproot->nodesize;
    heaproot->nodes[heaproot->nodesize++] = *data;
    while(tmpi > 0)
    {
        uint32_t tmpperant = (tmpi - 1) / 2;
        int tmpcmp = heaproot->nodes[tmpperant].keyuint >= heaproot->nodes[tmpi].keyuint;
        if(!heaproot->bigTreeFlag)
        {
            tmpcmp = !tmpcmp;
        }
        if(tmpcmp)
        {
            break;
        }
        SWAP_BASE_VAL(heaproot->nodes[tmpperant].keyuint, heaproot->nodes[tmpi].keyuint);
        tmpi = tmpperant;
    }
    return 1;
}
int heapRootGetTop(struct heapRootInform *heaproot, union heapNodeInform *data)
{
    if (!heaproot || !data)
    {
        logerrorc("");
        return -1;
    }
    if(heaproot->nodesize < 1)
    {
        return 0;
    }
    uint32_t tmpi = 0;
    *data = heaproot->nodes[0];
    heaproot->nodes[0] = heaproot->nodes[--heaproot->nodesize];
    while(tmpi < heaproot->nodesize)
    {
        uint32_t childleft = tmpi * 2 + 1, childright = tmpi * 2 + 2;
        uint32_t optchild = 0;
        int tmpcmp;
        if(childright < heaproot->nodesize)
        {
            tmpcmp = heaproot->nodes[childleft].keyuint >= heaproot->nodes[childright].keyuint;
            if(!heaproot->bigTreeFlag)
            {
                tmpcmp = !tmpcmp;
            }
            if(tmpcmp)
            {
                optchild = childleft;
            }
            else
            {
                optchild = childright;
            }
        }
        else if(childleft < heaproot->nodesize)
        {
            optchild = childleft;
        }
        else
        {
            break;
        }

        tmpcmp = heaproot->nodes[tmpi].keyuint >= heaproot->nodes[optchild].keyuint;
        if(!heaproot->bigTreeFlag)
        {
            tmpcmp = !tmpcmp;
        }
        if(tmpcmp)
        {
            break;
        }

        SWAP_BASE_VAL(heaproot->nodes[tmpi].keyuint, heaproot->nodes[optchild].keyuint);
        tmpi = optchild;
    }
    return 1;    
}

int heapRootPrintf(struct heapRootInform *heaproot)
{
    if (!heaproot)
    {
        logerrorc("");
        return -1;
    }
    logdebugc("heap size=%u, bigflag=%d", heaproot->nodesize, heaproot->bigTreeFlag);
    for(uint32_t i = 0; i < heaproot->nodesize; i++)
    {
        logdebugc("heap[%u]=%u", i, heaproot->nodes[i].keyuint);
    }
    return 0;
}